﻿package code
{
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.display.MovieClip;
	import flash.geom.Point;
	import flash.text.*;
	import flash.display.FrameLabel;
		
	public class Level extends MovieClip
	{
		// Background & HUD
		private var backgroundImage:Background;
		private var backgroundImage2:Background;
		private var hud:HUD;

		// The player/enemies/bullets
		private var player:Player;
		private var enemies:Dictionary;
		private var playerBullets:Dictionary;
		private var enemyBullets:Dictionary;
		
		// # enemies/bullets
		private var enemyCount:uint;
		private var playerBulletCount:uint;
		private var enemyBulletCount:uint;
		private var score:uint;
		private var numKills:uint;
		private var victory:Boolean;
		
		// Scroll speed for background  image
		private static var scrollFactor:int = 2;
		private static var LEVEL_LENGTH = 3000;
		private var currentLength:int = 0;
		
		private var enemySpawner:EnemySpawner;
		
		public static function get ScrollFactor():int { return scrollFactor; }
		
		public function Level() 
		{
			backgroundImage = new Background(720);
			addChildAt(backgroundImage, 0);
			backgroundImage2 = new Background(-backgroundImage.height + 720);
			addChildAt(backgroundImage2, 0);
			hud = new HUD(320, 720);
			addChild(hud);
			
			enemies = new Dictionary(true);
			playerBullets = new Dictionary(true);
			enemyBullets = new Dictionary(true);
			
			score = 0;
			numKills = 0;
			victory = false;
			
			player = new Player(320, 500);
			addChildAt(player, 2);
			
			enemySpawner = new EnemySpawner(this);
			enemySpawner.Load("data/enemies.xml");
		}
		
		// Accessors
		public function getKills():uint { return numKills; }
		public function getScore():uint { return score; }
		public function getVictory():Boolean { return victory; }
		
		// Deletion of elements
		public function addEnemy(enemyAdding:GenericEnemy)
		{
			enemies[enemyAdding] = enemyAdding;
			addChildAt(enemyAdding, 2);
			enemyCount++;
			
		}
		public function addPlayerBullet(bulletAdding:GenericBullet)
		{
			playerBullets[bulletAdding] = bulletAdding;
			addChild(bulletAdding);
			playerBulletCount++;
		}
		public function addEnemyBullet(bulletAdding:GenericBullet)
		{
			enemyBullets[bulletAdding] = bulletAdding;
			addChild(bulletAdding);
			enemyBulletCount++;
		}
		
		// Close the level
		public function closeLevel()
		{
			// Remove the enemies
			for each(var enemy:GenericEnemy in enemies)
			{
				removeEnemy(enemy);
			}
			for each(var playerBullet:GenericBullet in playerBullets)
			{
				removePlayerBullet(playerBullet);
			}
			for each(var enemyBullet:GenericBullet in enemyBullets)
			{
				removeEnemyBullet(enemyBullet);
			}
			player.cleanup();
			removeChild(backgroundImage);
			removeChild(backgroundImage2);
			removeChild(hud);
			removeChild(player);
		}
		// Removal of elements
		public function removeEnemy(enemyRemoving:GenericEnemy)
		{
			enemySpawner.CurrentWave.removeEnemy(enemyRemoving);
			enemyRemoving.destroy();
			
			delete enemies[enemyRemoving];
			removeChild(enemyRemoving);
			enemyCount--;
		}
		public function removePlayerBullet(bulletRemoving:GenericBullet)
		{
			delete playerBullets[bulletRemoving];
			removeChild(bulletRemoving);
			playerBulletCount--;
		}
		public function removeEnemyBullet(bulletRemoving:GenericBullet)
		{
			delete enemyBullets[bulletRemoving];
			removeChild(bulletRemoving);
			enemyBulletCount--;
		}
		
		// Update all of the objects
		public function update()
		{
			if(enemySpawner.Completed) //currentLength == LEVEL_LENGTH)
			{
				trace("end of level")
				victory = true;
				(parent as Document).endGame();
			}
			else if(!player.isDead())
			{
				if (enemySpawner.Ready)
				{
					enemySpawner.update();
				}
				
				//currentLength += scrollFactor;
				//trace(currentLength);
				
				// Update backgrounds and check to see if they go off the screen
				backgroundImage.move();
				backgroundImage2.move();
				if(backgroundImage.y > 720)
				{
					backgroundImage.y = backgroundImage2.y - backgroundImage.height;
				}
				if(backgroundImage2.y > 720)
				{
					backgroundImage2.y = backgroundImage.y - backgroundImage2.height;
				}
				
				player.update();
			
				// Update player bullets
				for each(var playerBullet:GenericBullet in playerBullets)
				{
					playerBullet.update();
					
					// Check collision with each enemy
					for each(var enemyCollideCheck:GenericEnemy in enemies)
					{
						if ((playerBullet as playerBullet.getClass()).hitbox.hitTestObject(
							(enemyCollideCheck as enemyCollideCheck.getClass()).hitbox))
						{
							removeEnemy(enemyCollideCheck);
							removePlayerBullet(playerBullet);
							score += 5;
							numKills++;
						}
					}
	
				}
				
				// Update enemy bullets
				for each(var enemyBullet:GenericBullet in enemyBullets)
				{
					if(!player.isDead())
					{
						enemyBullet.update();
						
						// Check collision with player
						if((enemyBullet as enemyBullet.getClass()).hitbox.hitTestObject(player.hitbox))
						{
							removeEnemyBullet(enemyBullet);
							
							player.isHit(5);
							// Decrement health
						}
					}
				}
				
				// Update the enemies
				for each(var enemy:GenericEnemy in enemies)
				{
					if(!player.isDead())
					{
						// Move the enemy
						enemy.update();
						
						// Check collision with enemy
						if ((enemy as enemy.getClass()).hitbox.hitTestObject(player.hitbox))
						{
							removeEnemy(enemy);
							
							player.isHit(5);
							// Decrement health
						}
						else if (enemy.y - enemy.height > stage.stageHeight)
						{
							removeEnemy(enemy);
						}
					}
				}
			}
			
			if(player.CheckForDeath())
			{
				trace("Defeated");
				(parent as Document).endGame();
			}	
			
			hud.UpdateScore(score);
			hud.UpdateHealth(player.GetHP());
		}
	}
}
